<?php

/**
 * Provides tree functionality in a parent-child tree structure
 */
class ParentChildTreeBehavior extends CActiveRecordBehavior{
	public $idAttribute = 'id';
	public $parentAttribute = 'parent_id';
	public $positionAttribute = 'position';
	
	/**
	 * Named scope. Get children of node.
	 * @return CActiveRecord the owner
	 */
	public function children(){
		$owner = $this->getOwner();
		$db = $owner->getDbConnection();
		$criteria = $owner->getDbCriteria();
		$alias = $db->quoteColumnName($owner->getTableAlias());

		$criteria->mergeWith(array(
			'condition' => $alias.'.'.$db->quoteColumnName($this->parentAttribute).'='.$owner->{$this->idAttribute},
			'order' => $alias.'.'.$db->quoteColumnName($this->positionAttribute),
		));
		
		return $owner;
	}
	
	/**
	 * Named scope. Get siblings of node.
	 * @return CActiveRecord the owner
	 */
	public function siblings(){
		$owner = $this->getOwner();
		$db = $owner->getDbConnection();
		$criteria = $owner->getDbCriteria();
		$alias = $db->quoteColumnName($owner->getTableAlias());
	
		if($owner->{$this->parentAttribute} === null){
			$criteria->mergeWith(array(
				'condition' => $alias.'.'.$db->quoteColumnName($this->parentAttribute).' IS NULL',
				'order' => $alias.'.'.$db->quoteColumnName($this->positionAttribute),
			));
		} else {
			$criteria->mergeWith(array(
				'condition' => $alias.'.'.$db->quoteColumnName($this->parentAttribute).'='.$owner->{$this->parentAttribute},
				'order' => $alias.'.'.$db->quoteColumnName($this->positionAttribute),
			));
		}
		
		return $owner;
	}
	
	/**
	 * Get record of node's parent.
	 * @return CActiveRecord the parent node. Null if no record is found
	 */
	public function getParent(){
		$owner = $this->getOwner();
		$db = $owner->getDbConnection();
		$criteria = $owner->getDbCriteria();
		$alias = $db->quoteColumnName($owner->getTableAlias());

		if($owner->{$this->parentAttribute} === null){
			return null;
		} else {
			$criteria->mergeWith(array(
				'condition' => $alias.'.'.$db->quoteColumnName($this->idAttribute).'='.$owner->{$this->parentAttribute},
			));
		}
		
		return $owner->find();
	}

	/**
	 * Get depth of node
	 * @return int depth of tree node, 0 if node is root
	 */
	public function getDepth(){
		$depth = 0;
		$model = $this->owner;
		while(($model = $model->getParent())!==null)
			$depth++;
		return $depth;
	}
}